#!/usr/bin/env node

const { spawn, execSync, exec } = require('child_process');
const fs = require('fs');
const path = require('path');
const readline = require('readline');
const util = require('util');

// 定义版本号
const VERSION = '1.3.0';

/**
 * 浏览器管理器工具
 * 提供浏览器实例管理的核心功能
 */
class BrowserManager {
  constructor(options = {}) {
    // 获取项目根目录
    const projectRoot = process.cwd();

    // 合并默认设置和用户设置
    this.options = Object.assign({
      userDataDir: path.join(projectRoot, '.browser-profiles'),
      configFile: path.join(projectRoot, '.browser-manager-config.json'),
      serverUrl: 'http://localhost:8080', // 默认服务器URL 
    }, options);

    // 确保用户数据目录存在
    if (!fs.existsSync(this.options.userDataDir)) {
      fs.mkdirSync(this.options.userDataDir, { recursive: true });
    }

    this.chrome = this._detectChrome();
    this.lastUsedProfile = null; // 上次使用的配置文件
    this.rl = null; // readline接口，用于CLI模式

    // 加载上次的配置信息
    this._loadConfig();
  }

  // 设置服务器URL
  setServerUrl(url) {
    this.options.serverUrl = url;
    return this;
  }
  // 设置 lastUsedProfile
  setProfile(profileName) {
    if (profileName) {
      this.lastUsedProfile = profileName;
    }
    return this;
  }

  // 获取上次使用的配置
  getLastUsedProfile() {
    return this.lastUsedProfile;
  }

  // 获取指定配置的完整路径
  getProfilePath(profileName) {
    return path.join(this.options.userDataDir, profileName);
  }

  // 加载配置文件
  _loadConfig() {
    try {
      if (fs.existsSync(this.options.configFile)) {
        const configData = JSON.parse(fs.readFileSync(this.options.configFile, 'utf8'));
        this.lastUsedProfile = configData.lastUsedProfile;
      }
    } catch (err) {
      console.error('[Browser Manager] 加载配置文件失败:', err.message);
    }
  }

  // 保存配置文件
  _saveConfig() {
    try {
      const configData = {
        lastUsedProfile: this.lastUsedProfile
      };
      fs.writeFileSync(this.options.configFile, JSON.stringify(configData, null, 2), 'utf8');
    } catch (err) {
      console.error('[Browser Manager] 保存配置文件失败:', err.message);
    }
  }

  // 只检测 Chrome 浏览器
  // 检测 Chrome 浏览器，在Windows上如果没有Chrome则使用Edge
  _detectChrome() {
    const platform = process.platform;
    let chromePath = null;

    try {
      if (platform === 'darwin') {
        // macOS
        const path = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
        if (fs.existsSync(path)) {
          chromePath = path;
        }
      } else if (platform === 'win32') {
        // Windows - 首先检查Chrome
        const chromePaths = [
          'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
          'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
        ];

        for (const path of chromePaths) {
          if (fs.existsSync(path)) {
            return { name: 'Google Chrome', command: path };
          }
        }

        // 如果没有找到Chrome，尝试查找Edge
        const edgePaths = [
          'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',
          'C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe',
        ];

        for (const path of edgePaths) {
          if (fs.existsSync(path)) {
            return { name: 'Microsoft Edge', command: path };
          }
        }
      } else if (platform === 'linux') {
        // Linux
        try {
          chromePath = execSync('which google-chrome').toString().trim();
        } catch (e) {
          // Chrome 不存在
        }
      }

      return chromePath ? { name: 'Google Chrome', command: chromePath } : null;
    } catch (error) {
      console.error('[Browser Manager] 检测浏览器时出错:', error.message);
      return null;
    }
  }

  // 获取所有Chrome运行实例
  async getAllRunningInstances() {
    return await this._discoverRunningInstances();
  }

  // 启动浏览器实例
  launchBrowserInstance(profileName) {
    if (!this.chrome) {
      console.error('[Browser Manager] 错误: 未找到 Google Chrome 浏览器');
      return null;
    }

    // 如果没有指定配置名称，并且有上次使用的配置，则使用上次的配置
    if (!profileName && this.lastUsedProfile) {
      profileName = this.lastUsedProfile;
    } else if (!profileName) {
      // 如果没有指定配置名称，也没有上次配置，创建默认配置名称
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      profileName = `chrome-${timestamp}`;
    }

    // 记录当前使用的配置
    this.lastUsedProfile = profileName;
    this._saveConfig();

    const userDataPath = path.join(this.options.userDataDir, profileName);

    // 确保用户数据目录存在
    if (!fs.existsSync(userDataPath)) {
      fs.mkdirSync(userDataPath, { recursive: true });
    }

    // 检查是否已有该配置的实例在运行
    this._discoverRunningInstances().then(instances => {
      const runningInstance = instances.find(inst => inst.profileName === profileName);
      if (runningInstance) {
        console.log(`[Browser Manager] 配置 ${profileName} 的实例已在运行中，PID: ${runningInstance.pid}`);
      }
    });

    // Chrome 命令行参数
    const args = [
      `--user-data-dir=${userDataPath}`,
      '--no-first-run',             // 禁止首次运行提示
      '--no-default-browser-check', // 禁止默认浏览器检查
      '--disable-sync',             // 禁止同步提示
      '--disable-features=TranslateUI', // 禁用翻译提示
      '--disable-signin-promo',     // 禁止登录提示
      '--disable-infobars',         // 禁止信息栏
      '--mute-notifications',       // 静音通知
      '--from-newbrowser',          // 标记这是由我们的工具启动的实例
      this.options.serverUrl
    ];
    try {
      const process = spawn(this.chrome.command, args, {
        detached: true,
        stdio: 'ignore'
      });

      // 允许父进程退出而不影响子进程
      process.unref();

      return profileName;
    } catch (error) {
      console.error(`[Browser Manager] 启动浏览器失败:`, error);
      return null;
    }
  }

  // 停止浏览器实例
  async stopBrowserInstance(profileName) {
    const instances = await this._discoverRunningInstances();
    const instance = instances.find(inst => inst.profileName === profileName);

    if (!instance) {
      return false;
    }

    try {
      process.kill(instance.pid);
      return true;
    } catch (error) {
      console.error(`[Browser Manager] 停止浏览器实例失败: ${profileName}`, error);
      return false;
    }
  }

  // 关闭所有浏览器实例
  async closeAllInstances() {
    const instances = await this._discoverRunningInstances();

    if (instances.length === 0) {
      return 0;
    }

    let closedCount = 0;

    for (const instance of instances) {
      try {
        process.kill(instance.pid);
        closedCount++;
      } catch (error) {
        console.error(`[Browser Manager] 关闭实例 ${instance.profileName} 失败:`, error);
      }
    }

    return closedCount;
  }

  /**
 * 从系统进程列表中发现由本工具启动的Chrome浏览器实例
 * @returns {Promise<Array>} 发现的实例数组
 */
  async _discoverRunningInstances() {
    try {
      // 根据操作系统平台选择不同的命令
      const platform = process.platform;
      let processes = [];

      if (platform === 'win32') {
        // Windows 平台
        processes = await this._getWindowsProcesses();

        // 在Windows上，如果无法获取完整命令行信息，添加警告
        const hasFullCommandLine = processes.some(proc =>
          proc.command && proc.command.includes('--user-data-dir='));

        if (processes.length > 0 && !hasFullCommandLine) {
          console.log('[Browser Manager] 警告: 无法获取完整命令行信息，某些浏览器实例可能无法识别。');
        }
      } else if (platform === 'darwin' || platform === 'linux') {
        // macOS 或 Linux 平台
        processes = await this._getMacLinuxProcesses();
      } else {
        console.error(`[Browser Manager] 不支持的平台: ${platform}`);
        return [];
      }

      // 筛选出命令行中包含 .browser-profiles 和 --user-data-dir 的Chrome进程（主进程）
      const discoveredInstances = [];

      // 首先筛选包含 --user-data-dir 和 .browser-profiles 的进程
      const mainProcesses = processes.filter(proc =>
        proc.command &&
        proc.command.includes('--user-data-dir=') &&
        proc.command.includes('.browser-profiles') &&
        proc.command.includes('--from-newbrowser')
      );

      for (const proc of mainProcesses) {
        // 从命令行参数中提取用户数据目录
        const userDataDirMatch = proc.command.match(/--user-data-dir=([^\s"']+|"[^"]+"|'[^']+')/);
        if (userDataDirMatch) {
          let userDataPath = userDataDirMatch[1];
          // 移除可能的引号
          userDataPath = userDataPath.replace(/^["']|["']$/g, '');

          // 检查路径是否存在
          if (fs.existsSync(userDataPath)) {
            const profileName = path.basename(userDataPath);

            discoveredInstances.push({
              profileName,
              pid: proc.pid,
              userDataPath,
              createdAt: new Date().toISOString(),
              status: 'running'
            });
          }
        }
      }

      return discoveredInstances;
    } catch (error) {
      console.error('[Browser Manager] 发现运行实例出错:', error);
      return [];
    }
  }
  /**
 * 获取Windows系统中的Chrome或Edge进程列表
 * @returns {Promise<Array>} 包含pid和命令行的进程对象数组
 */
  async _getWindowsProcesses() {
    try {
      const execPromise = util.promisify(exec);
      // 检查浏览器类型
      const isEdge = this.chrome && this.chrome.name === 'Microsoft Edge';
      const processName = isEdge ? 'msedge' : 'chrome';

      // 使用PowerShell命令替代wmic
      const psCommand = `powershell -command "Get-Process ${processName} | Where-Object {$_.Path -ne $null} | ForEach-Object { $_.Id.ToString() + ',' + (Get-CimInstance Win32_Process -Filter ('ProcessId = ' + $_.Id)).CommandLine } | ConvertTo-Json"`;

      const { stdout } = await execPromise(psCommand);

      const processes = [];
      try {
        // 解析JSON输出
        const cmdLines = JSON.parse(stdout);
        const processLines = Array.isArray(cmdLines) ? cmdLines : [cmdLines];

        for (const line of processLines) {
          if (typeof line === 'string') {
            const parts = line.split(',');
            if (parts.length >= 2) {
              const pid = parseInt(parts[0], 10);
              const command = parts.slice(1).join(',');

              if (!isNaN(pid) && command) {
                processes.push({ pid, command });
              }
            }
          }
        }
      } catch (parseError) {
        console.error('[Browser Manager] 解析PowerShell输出失败:', parseError.message);
      }

      // 如果PowerShell方法失败，尝试使用更基本的tasklist命令
      if (processes.length === 0) {
        console.log('[Browser Manager] 尝试备用方法获取进程信息...');
        const exeName = isEdge ? 'msedge.exe' : 'chrome.exe';
        const { stdout: tasklistOutput } = await execPromise(`tasklist /FI "IMAGENAME eq ${exeName}" /FO CSV /NH`);

        const lines = tasklistOutput.trim().split('\n');
        for (const line of lines) {
          // CSV格式: "Image Name","PID","Session Name","Session#","Mem Usage"
          const match = line.match(/"[^"]+",\s*"(\d+)"/);
          if (match && match[1]) {
            const pid = parseInt(match[1], 10);
            processes.push({
              pid,
              command: exeName // 只能获取进程名，无法获取完整命令行
            });
          }
        }
      }

      return processes;
    } catch (error) {
      console.error('[Browser Manager] 获取Windows进程列表失败:', error.message);
      return [];
    }
  }
  /**
   * 获取Mac/Linux系统中的Chrome进程列表
   * @returns {Promise<Array>} 包含pid和命令行的进程对象数组
   */
  async _getMacLinuxProcesses() {
    try {
      const execPromise = util.promisify(exec);

      // 根据系统选择正确的Chrome进程名称
      const isLinux = process.platform === 'linux';
      const processName = isLinux ? 'google-chrome' : 'Google Chrome';

      // 使用更详细的命令获取完整的命令行参数
      const { stdout } = await execPromise(`ps -ax -o pid,command | grep "${processName}"`);

      const lines = stdout.trim().split('\n');
      const processes = [];

      for (const line of lines) {
        // 忽略grep自身的进程
        if (line.includes('grep')) continue;

        // 格式: PID COMMAND
        const match = line.trim().match(/^(\d+)\s+(.+)$/);
        if (match) {
          const pid = parseInt(match[1], 10);
          const command = match[2];

          if (!isNaN(pid)) {
            processes.push({ pid, command });
          }
        }
      }

      return processes;
    } catch (error) {
      console.error('[Browser Manager] 获取Mac/Linux进程列表失败:', error.message);
      return [];
    }
  }

  // 获取所有配置文件
  getAllProfiles() {
    try {
      return fs.readdirSync(this.options.userDataDir)
        .filter(item => {
          const itemPath = path.join(this.options.userDataDir, item);
          return fs.statSync(itemPath).isDirectory();
        });
    } catch (err) {
      console.error('[Browser Manager] 读取配置文件失败:', err.message);
      return [];
    }
  }

  // 删除配置目录
  deleteProfile(profileName) {
    // 构建配置目录路径
    const profilePath = path.join(this.options.userDataDir, profileName);

    if (!fs.existsSync(profilePath)) {
      return false;
    }

    try {
      // 递归删除目录内容
      this._removeDirectory(profilePath);

      // 如果删除的是最后使用的配置，清空该记录
      if (this.lastUsedProfile === profileName) {
        this.lastUsedProfile = null;
        this._saveConfig();
      }

      return true;
    } catch (err) {
      console.error(`[Browser Manager] 删除配置目录失败:`, err.message);
      return false;
    }
  }

  // 递归删除目录
  _removeDirectory(dirPath) {
    if (fs.existsSync(dirPath)) {
      fs.readdirSync(dirPath).forEach(file => {
        const curPath = path.join(dirPath, file);
        if (fs.lstatSync(curPath).isDirectory()) {
          // 递归删除子目录
          this._removeDirectory(curPath);
        } else {
          // 删除文件
          fs.unlinkSync(curPath);
        }
      });
      fs.rmdirSync(dirPath);
    }
  }

  // 启动命令行界面
  startCLI() {
    if (this.rl) return this; // 防止重复启动

    // 清屏以便更明显地显示浏览器管理器界面
    // console.clear();

    // console.log('\n\n');
    // console.log('┌──────────────────────────────────────────────────────────────┐');
    // console.log('│                浏览器实例管理器 (命令行版)                   │');
    // console.log('├──────────────────────────────────────────────────────────────┤');
    // console.log(`│ 开发服务器地址: ${this.options.serverUrl.padEnd(45)} │`);
    // console.log(`│ 用户数据目录: ${this.options.userDataDir.padEnd(48)} │`);
    // console.log(`│ 上次使用配置: ${(this.lastUsedProfile || '无').padEnd(48)} │`);
    // console.log('│ 输入 "help" 查看可用命令                                    │');
    // console.log('└──────────────────────────────────────────────────────────────┘\n');

    // 检查是否有可用的浏览器
    if (!this.chrome) {
      console.log('[Browser Manager] 错误：未找到 Google Chrome 浏览器');
      return this;
    }

    // 创建命令行界面
    this.rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout,
      prompt: '浏览器管理器> '
    });

    // 处理命令行输入
    this.rl.prompt();

    this.rl.on('line', async (line) => {
      const command = line.trim();
      await this._processCLICommand(command);
      this.rl.prompt();
    }).on('close', () => {
      console.log('\n浏览器管理器已退出');
      // 确保关闭所有浏览器实例
      this.closeAllInstances().then(() => {
        process.exit(0);
      });
    });

    // 进入CLI后自动检查运行中的实例
    this.getAllRunningInstances().then(instances => {
      if (instances.length > 0) {
        console.log(`[Browser Manager] 发现 ${instances.length} 个运行中的浏览器实例`);
      }

      // 添加自动启动功能
      if (this.lastUsedProfile && instances.length === 0) {
        console.log(`[自动启动] 检测到上次使用的配置: ${this.lastUsedProfile}`);
        console.log('[自动启动] 自动启动浏览器，按Ctrl+C取消...');

        setTimeout(() => {
          console.log(`[自动启动] 使用 Chrome 启动上次的配置...`);
          this.launchBrowserInstance(this.lastUsedProfile);
          this.rl.prompt();
        }, 0);
      } else {
        console.log(`[自动启动] 没有上次使用的配置，或者有运行中的实例`);
        this.launchBrowserInstance(this.lastUsedProfile);
        this.rl.prompt();
      }
    });

    return this;
  }

  // 处理CLI命令
  async _processCLICommand(command) {
    const parts = command.split(' ');
    const cmd = parts[0].toLowerCase();

    try {
      switch (cmd) {
        case 'help':
          this._printHelp();
          break;
        case 'list':
          await this._handleList();
          break;
        case 'launch':
          this._handleLaunch(parts.slice(1));
          break;
        case 'stop':
          await this._handleStop(parts[1]);
          break;
        case 'stopall':
          await this._handleStopAll();
          break;
        case 'delete':
          await this._handleDelete(parts[1]);
          break;
        case 'profiles':
          this._handleProfiles();
          break;
        case 'clear':
          console.clear();
          break;
        case 'exit':
          this.rl.close();
          break;
        case '':
          // 忽略空行
          break;
        default:
          console.log(`未知命令: ${cmd}. 输入 "help" 查看可用命令.`);
      }
    } catch (error) {
      console.error(`命令执行错误: ${error.message}`);
    }
  }

  // 打印帮助信息
  _printHelp() {
    console.log('\n可用命令:');
    console.log('  help          - 显示此帮助信息');
    console.log('  list          - 列出所有浏览器配置和运行状态');
    console.log('  launch        - 启动一个新的 Chrome 实例（创建新配置）');
    console.log('  launch [配置名称] - 使用指定配置名称启动 Chrome');
    console.log('  stop [配置名称] - 停止指定的浏览器实例');
    console.log('  stopall       - 停止所有浏览器实例');
    console.log('  delete [配置名称] - 删除指定的配置目录及其所有数据');
    console.log('  profiles      - 列出所有可用的配置文件');
    console.log('  clear         - 清屏');
    console.log('  exit          - 退出浏览器管理器\n');
  }

  // 处理list命令
  async _handleList() {
    const instances = await this.getAllRunningInstances();
    const profiles = this.getAllProfiles();

    console.log('\n浏览器配置和实例:');

    if (profiles.length === 0) {
      console.log('  没有找到任何配置文件');
      return;
    }

    profiles.forEach((profileName, index) => {
      const isLastUsed = profileName === this.lastUsedProfile;
      const prefix = isLastUsed ? '* ' : '  ';
      const instance = instances.find(inst => inst.profileName === profileName);

      console.log(`${prefix}${index + 1}. ${profileName}${isLastUsed ? ' (上次使用)' : ''}`);

      if (instance) {
        console.log(`     状态: 运行中, PID: ${instance.pid}`);
        console.log(`     用户数据路径: ${instance.userDataPath}`);
      } else {
        console.log('     无运行实例');
      }
      console.log(''); // 添加空行分隔
    });

    console.log(`当前运行实例: ${instances.length}`);
  }

  // 处理launch命令
  _handleLaunch(args) {
    const profileName = args[0];  // 可能是 undefined
    const launchedProfile = this.launchBrowserInstance(profileName);

    if (launchedProfile) {
      console.log(`浏览器实例已启动, 配置: ${launchedProfile}`);
    } else {
      console.log(`启动浏览器实例失败`);
    }
  }

  // 处理stop命令
  async _handleStop(profileName) {
    if (!profileName) {
      console.log('错误: 请指定配置名称. 使用 "list" 查看可用的配置.');
      return;
    }

    const success = await this.stopBrowserInstance(profileName);
    if (success) {
      console.log(`已停止配置 ${profileName} 的实例`);
    } else {
      console.log(`停止配置 ${profileName} 的实例失败或不存在`);
    }
  }

  // 处理stopall命令
  async _handleStopAll() {
    const count = await this.closeAllInstances();
    if (count > 0) {
      console.log(`已关闭 ${count} 个浏览器实例`);
    } else {
      console.log('没有需要关闭的浏览器实例');
    }
  }

  // 处理delete命令
  async _handleDelete(profileName) {
    if (!profileName) {
      console.log('错误: 请指定配置名称. 使用 "list" 查看可用的配置.');
      return;
    }

    // 先检查是否有实例在运行
    const instances = await this.getAllRunningInstances();
    const runningInstance = instances.find(inst => inst.profileName === profileName);

    if (runningInstance) {
      console.log(`错误: 配置 "${profileName}" 有正在运行的实例，请先停止它。`);
      return;
    }

    const success = this.deleteProfile(profileName);
    if (success) {
      console.log(`已删除配置 ${profileName}`);
    } else {
      console.log(`删除配置 ${profileName} 失败或不存在`);
    }
  }

  // 处理profiles命令
  _handleProfiles() {
    const profiles = this.getAllProfiles();

    console.log('\n可用的浏览器配置:');

    if (profiles.length === 0) {
      console.log('  没有找到任何配置文件');
    } else {
      profiles.forEach((profileName, index) => {
        const isLastUsed = profileName === this.lastUsedProfile;
        const profilePath = this.getProfilePath(profileName);

        console.log(`  ${index + 1}. ${profileName}${isLastUsed ? ' (上次使用)' : ''}`);
        console.log(`     路径: ${profilePath}`);
      });
    }

    console.log('\n使用 "launch [配置名称]" 启动指定配置');
  }
}

// 如果直接运行此脚本，则执行默认操作（启动一个实例）
if (require.main === module) {
  const manager = new BrowserManager();
  const launchedProfile = manager.launchBrowserInstance();
  if (launchedProfile) {
    console.log(`[Browser Manager] 浏览器实例已启动，配置: ${launchedProfile}`);
  } else {
    console.log('[Browser Manager] 启动浏览器实例失败');
  }
}

// 导出浏览器管理器类，以便在其他文件中使用
module.exports = BrowserManager;
